﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Drawing;
using SGP;
using Microsoft.DirectX.Direct3D;
using System.Threading;

namespace Particle_Editor
{
    class Emitter
    {
        struct Particle
        {
            public float PosX;
            public float PosY;
            public float CurLife;
            public float CurVelX;
            public float CurVelY;
            public float CurScaleX;
            public float CurScaleY;
            public bool isAlive;
            public Color CurColor;
            public bool haslife;
        }

        Particle[]         particles = new Particle[10];
        public Rectangle   EmitterRect;
        public int         ImageID;
        public int         SourceBlend;
        public int         DestBlend;
        public float       MaxLife;
        public float       MinLife;
        public bool        looping;
        public Color       StartColor;
        public Color       EndColor;
        public float       MaxParticles;
        public float       ScaleX;
        public float       ScaleY;
        public float       VelX;
        public float       VelY;
        public float       EndVelX;
        public float       EndVelY;
        public float       EndScaleX;
        public float       EndScaleY;
        public float       Rotation;

        public Emitter()
        {
            EmitterRect = new Rectangle(0, 0, 0, 0);
            ImageID = -1;
            SourceBlend = 0;
            DestBlend = 0;
            MaxLife = 0.0f;
            MinLife = 0.0f;
            looping = false;
            StartColor = new Color();
            EndColor = new Color();
            MaxParticles = 0.0f;
            ScaleX = 1.0f;
            ScaleY = 1.0f;
            VelX = 0.0f;
            VelY = 0.0f;
            Rotation = 0.0f;
            EndVelX = 0.0f;
            EndVelY = 0.0f;
            EndScaleX = 0.0f;
            EndScaleY = 0.0f;
        }

        public Emitter(Rectangle ER, int ID, int SB, int DB, float MinL, float MaxL,
                       bool loop, Color SC, Color EC, float MP, float SX, float SY, float VX,
                        float VY, float Rot, float ESX, float ESY, float EVX, float EVY)
    {
        EmitterRect = ER;
        ImageID = ID;
        SourceBlend = SB;
        DestBlend = DB;
        MinLife = MinL;
        MaxLife = MaxL;
        looping = loop;
        StartColor = SC;
        EndColor = EC;
        MaxParticles = MP;
        ScaleX = SX;
        ScaleY = SY;
        VelX = VX;
        VelY = VY;
        Rotation = Rot;
        EndVelX = EVX;
        EndVelY = EVY;
        EndScaleX = ESX;
        EndScaleY = ESY;
        particles = new Particle[(int)MaxParticles];
    }

        public void Render()
        {
            ManagedDirect3D.Instance.Device.SetRenderState(RenderStates.SourceBlend, SourceBlend);
            ManagedDirect3D.Instance.Device.SetRenderState(RenderStates.DestinationBlend, DestBlend);           

            for (uint i = 0; i < MaxParticles; i++)
            {
                if (particles[i].isAlive == true)
                {
                    if (ImageID != -1)
                    {
                        ManagedTextureManager.Instance.Draw(ImageID, (int)particles[i].PosX - (EmitterRect.Width+ManagedTextureManager.Instance.GetTextureWidth(ImageID))/2, 
                            (int)particles[i].PosY - (EmitterRect.Height + ManagedTextureManager.Instance.GetTextureHeight(ImageID))/2,
                            particles[i].CurScaleX, particles[i].CurScaleY, Rectangle.Empty,
                            ManagedTextureManager.Instance.GetTextureWidth(ImageID) / 2, ManagedTextureManager.Instance.GetTextureHeight(ImageID) / 2,
                            Rotation, particles[i].CurColor);
                    }
                }
            }
        }

        public void Update(float ElapsedTime)
        {
            for (uint i = 0; i < MaxParticles; i++)
            {   
                if (particles[i].haslife == false)
                {
                    Random rand = new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0));

                    if (MinLife > MaxLife)
                    {
                        MinLife = 0;
                    }

                    particles[i].CurLife = rand.Next((int)MinLife, (int)MaxLife);
                    particles[i].CurScaleX = ScaleX;
                    particles[i].CurScaleY = ScaleY;
                    particles[i].CurColor = StartColor;
                    particles[i].CurVelX = VelX;
                    particles[i].CurVelY = VelY;
                    particles[i].isAlive = true;
                    particles[i].haslife = true;

                    float positionX = (float)(EmitterRect.Right - EmitterRect.Left);
                    float positionY = (float)(EmitterRect.Bottom - EmitterRect.Top);

                    if (positionX == 0)
                        positionX = 1;
                    else
                        positionX = rand.Next(EmitterRect.Left, EmitterRect.Right);

                    if (positionY == 0)
                        positionY = 1;
                    else
                        positionY = rand.Next(EmitterRect.Top, EmitterRect.Bottom);

                    particles[i].PosX = positionX;
                    particles[i].PosY = positionY;
                }
            }

            for (uint i = 0; i < MaxParticles; i++)
            {
                if (particles[i].isAlive == true)
                {
                    particles[i].CurColor = ColorOperator.Lerp(StartColor, EndColor, (particles[i].CurLife / MaxLife)); //(particles[i].CurLife / MaxLife - particles[i].CurLife));
                    particles[i].CurLife += ElapsedTime;
                    particles[i].CurVelX = Lerp(VelX, EndVelX, (particles[i].CurLife / MaxLife));
                    particles[i].CurVelY = Lerp(VelY, EndVelY, (particles[i].CurLife / MaxLife));
                    particles[i].PosX += (particles[i].CurVelX * (ElapsedTime));
                    particles[i].PosY += (particles[i].CurVelY * (ElapsedTime));
                    particles[i].CurScaleX = Lerp(ScaleX, EndScaleX, (particles[i].CurLife / MaxLife));
                    particles[i].CurScaleY = Lerp(ScaleY, EndScaleY, (particles[i].CurLife / MaxLife));

                    if (particles[i].CurLife >= MaxLife)
                    {
                        particles[i].isAlive = false;

                        if (looping == true)
                        {
                           particles[i] = Reset(particles[i]);
                           particles[i].haslife = false;
                        }
                    }
                }

                if (looping == true)
                {
                    particles[i].isAlive = true;
                }
            }
        }

        Particle Reset(Particle P)
        {
            Random rand = new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0));

            if (MinLife > MaxLife)
            {
                MinLife = 0;
            }

            P.CurLife = rand.Next((int)MinLife, (int)MaxLife);
            P.CurScaleX = ScaleX;
            P.CurScaleY = ScaleY;
            P.CurColor = StartColor;
            P.CurVelX = VelX;
            P.CurVelY = VelY;
            P.isAlive = true;

            float positionX = (float)(EmitterRect.Right - EmitterRect.Left);
            float positionY = (float)(EmitterRect.Bottom - EmitterRect.Top);

            if (positionX == 0)
                positionX = 1;
            else
                positionX = rand.Next(EmitterRect.Left, EmitterRect.Right);

            if (positionY == 0)
                positionY = 1;
            else
                positionY = rand.Next(EmitterRect.Top, EmitterRect.Bottom);

            P.PosX = positionX;
            P.PosY = positionY;

            return P;
        }

        public void SetParticles(float numParticles)
        {
            particles = new Particle[(int)numParticles];
        }

        public float Lerp(float StartV, float EndV, float s)
        {
            return StartV + ((EndV - StartV) * s);
        }
    }
}
